package com.hsy.crm.web.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hsy.crm.web.domain.cm.App;
import com.hsy.crm.web.domain.cm.PageResult;
import com.hsy.crm.web.domain.cm.Unified;
import com.hsy.crm.web.domain.entity.SplitProduct;
import com.hsy.crm.web.domain.entity.SplitProductDetail;
import com.hsy.crm.web.domain.entity.StoreProduct;
import com.hsy.crm.web.domain.ex.ServiceException;
import com.hsy.crm.web.domain.po.splitProduct.SplitProductDetailGetPo;
import com.hsy.crm.web.domain.po.splitProduct.SplitProductGetPo;
import com.hsy.crm.web.domain.po.splitProduct.SplitProductPagePo;
import com.hsy.crm.web.domain.vo.splitProduct.SplitProductPageVo;
import com.hsy.crm.web.domain.vo.splitProduct.SplitVo;
import com.hsy.crm.web.mapper.SplitProductDetailMapper;
import com.hsy.crm.web.mapper.SplitProductMapper;
import com.hsy.crm.web.service.base.BaseService;
import com.hsy.crm.web.service.base.CacheService;
import com.hsy.crm.web.service.base.DataInitService;
import com.hsy.crm.web.utils.CalcUtils;
import com.hsy.crm.web.utils.ServiceUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class SplitProductService extends BaseService<SplitProduct> {

    @Autowired
    SplitProductMapper splitProductMapper;

    @Autowired
    SplitProductDetailMapper splitProductDetailMapper;

    @Autowired
    StoreProductService storeProductService;

    @Autowired
    MessageService messageService;

    @Transactional
    public Unified<Integer> examine(SplitVo splitVo) {
        Unified<Integer> unified = new Unified<>();
        SplitProduct splitProduct = splitVo.getSplitProduct();
        splitProduct.setCustomerId(splitVo.getCustomerId());
        this.updateStatus(splitProduct.getId(),App.Status.SH,splitProduct.getCustomerId());
        splitProduct.setCompanyId(splitVo.getLoginCompanyId());

        this.update_store_product_exam(splitVo);
        messageService.addMessage(splitProduct,splitVo.getSplitProductDetails(),App.ExamType.EXAMINE);
        return unified;
    }

    @Transactional
    public Unified<Integer> doInvalid(SplitProduct splitProduct) {
        Unified<Integer> unified = new Unified<>();
        splitProduct = this.getSplitProduct(splitProduct);
        this.updateStatus(splitProduct.getId(),App.Status.BC,splitProduct.getCustomerId());

        splitProduct.setCompanyId(splitProduct.getLoginCompanyId());
        List<SplitProductDetail> orderDetails = this.getOrderDetails(splitProduct);

        this.update_store_product_invalid(splitProduct,orderDetails);
        messageService.addMessage(splitProduct,orderDetails,App.ExamType.INVALID);
        return unified;
    }

    @Transactional
    public Unified<SplitProduct> insertSplitProduct(SplitVo splitVo) {
        Unified<SplitProduct> unified = new Unified<>();
        // master
        SplitProduct splitProduct = splitVo.getSplitProduct();
        splitProduct.setLoginUserId(splitVo.getLoginUserId());
        splitProduct.setCode(DataInitService.getOrderCode());
        splitProduct.setStatus(App.Status.BC);
        splitProduct.setLoginCompanyId(splitVo.getLoginCompanyId());
        splitProduct.setCustomerId(splitVo.getCustomerId());
        this.insert(splitProduct);

        // slave details
        this.insertDetails(splitProduct.getId(),splitVo);

        if( splitVo.getSaveType() == App.SaveType.EXAMINE ){
            this.examine(splitVo);
        }

        unified.setData(splitProduct);
        return unified;
    }

    @Transactional
    public Unified<SplitProduct> updateSplitProduct(SplitVo splitVo) {
        Unified<SplitProduct> unified = new Unified<>();
        SplitProduct splitProduct = splitVo.getSplitProduct();
        splitProduct.setLoginUserId(splitVo.getLoginUserId());
        splitProduct.setCustomerId(splitVo.getCustomerId());

        this.update(splitProduct);
        this.deleteDetails(splitProduct);
        this.insertDetails(splitProduct.getId(),splitVo);

        if( splitVo.getSaveType() == App.SaveType.EXAMINE ){
            this.examine(splitVo);
        }
        unified.setData(splitProduct);
        return unified;
    }

    @Transactional
    public Unified<Integer> deleteSplitProduct(SplitProduct splitProduct) {
        this.deleteDetails(splitProduct);
        return Unified.newInstance(this.delete(splitProduct));
    }

    public PageResult<SplitProductPagePo> page(SplitProductPageVo splitProductPageVo) {
        Page page = PageHelper.startPage(splitProductPageVo.getPage(),splitProductPageVo.getLimit());
        PageResult<SplitProductPagePo> pageResult = new PageResult<>();
        pageResult.setRows(splitProductMapper.page(splitProductPageVo));
        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    public Unified<SplitProductGetPo> getOrder(SplitProduct splitProduct) {
        Unified<SplitProductGetPo> unified = new Unified<>();

        SplitProductGetPo splitProductGetPo = new SplitProductGetPo();
        SplitProduct dbSplitProduct = splitProductMapper.selectByPrimaryKey(splitProduct);
        List<SplitProductDetailGetPo> details  = splitProductMapper.getOrder(splitProduct);

        splitProductGetPo.setDetails(details);
        splitProductGetPo.setId(dbSplitProduct.getId());
        splitProductGetPo.setCode(dbSplitProduct.getCode());
        splitProductGetPo.setDate(dbSplitProduct.getDate());
        splitProductGetPo.setType(dbSplitProduct.getType());
        splitProductGetPo.setStatus(dbSplitProduct.getStatus());

        unified.setData(splitProductGetPo);
        return unified;
    }

    private List<SplitProductDetail> getOrderDetails(SplitProduct order){
        SplitProductDetail orderDetail = new SplitProductDetail();
        orderDetail.setSplitProductId(order.getId());
        orderDetail.setCustomerId(order.getCustomerId());
        return splitProductDetailMapper.select(orderDetail);
    }

    private void update_store_product_exam(SplitVo splitVo){
        for( SplitProductDetail detail : splitVo.getSplitProductDetails() ){
            StoreProduct storeProduct = getStoreProduct(splitVo.getCustomerId(),splitVo.getLoginCompanyId(),detail);
            storeProduct.setPrice(getPrice(detail));
            storeProductService.update(storeProduct,getDirection(splitVo.getSplitProduct().getType(),detail));
            detail.setSplitProductId(storeProduct.getId());
        }
    }

    private void update_store_product_invalid(SplitProduct order,List<SplitProductDetail> details){
        for( SplitProductDetail detail : details ){
            StoreProduct storeProduct = getStoreProduct(order.getCustomerId(),order.getLoginCompanyId(),detail);
            storeProduct.setPrice(getPrice(detail));
            storeProductService.update(storeProduct,getDirection(order.getType(),detail));
        }
    }

    public static int getDirection(int splitProducType,SplitProductDetail detail){
        if( splitProducType == 1 ){
            //拆
            if( detail.getType() == 1 ){
                //组合件
                return App.StoreType.OUT;
            }else{
                return App.StoreType.IN;
            }
        }else{
            //装
            if( detail.getType() == 1 ){
                //组合件
                return App.StoreType.IN;
            }else{
                return App.StoreType.OUT;
            }
        }
    }

    public static Long getPrice(SplitProductDetail orderDetail){
        double totalPrice = CalcUtils.mul(orderDetail.getNumber(),orderDetail.getPrice());
        totalPrice = CalcUtils.div(totalPrice,App.DECIMAL.DIV);
        return ((Double)totalPrice).longValue();
    }

    private static StoreProduct getStoreProduct(String customerId,Long companyId,SplitProductDetail orderDetail){
        StoreProduct storeProduct = new StoreProduct();
        storeProduct.setCompanyId(companyId);
        storeProduct.setProductId(orderDetail.getProductId());
        storeProduct.setStoreId(orderDetail.getStoreId());
        storeProduct.setUnitId(orderDetail.getUnitId());
        storeProduct.setCustomerId(customerId);
        storeProduct.setNumber(orderDetail.getNumber());

        return storeProduct;
    }


    private void insertDetails(Long splitProductId,SplitVo splitVo){
        List<SplitProductDetail> details = splitVo.getSplitProductDetails();
        for (SplitProductDetail detail : details){

            if( !CacheService.hasProductId(splitVo.getCustomerId(),detail.getProductId())){
                throw new ServiceException(detail.getProductId());
            }

            detail.setSplitProductId(splitProductId);
            detail.setLoginUserId(splitVo.getLoginUserId());
            detail.setCustomerId(splitVo.getCustomerId());
            ServiceUtils.init_entity_insert(detail);
            splitProductDetailMapper.insert(detail);
        }
    }

    private void deleteDetails(SplitProduct splitProduct){
        SplitProductDetail detail = new SplitProductDetail();
        detail.setSplitProductId(splitProduct.getId());
        detail.setCustomerId(splitProduct.getCustomerId());
        splitProductDetailMapper.delete(detail);
    }

    private void updateStatus(Long orderId,Integer status,String customerId){
        SplitProduct order = new SplitProduct();
        order.setId(orderId);
        order.setStatus(status);
        order.setCustomerId(customerId);
        splitProductMapper.updateByPrimaryKeySelective(order);
    }

    private SplitProduct getSplitProduct(SplitProduct splitProduct){
        SplitProduct select = new SplitProduct();
        select.setCustomerId(splitProduct.getCustomerId());
        select.setId(splitProduct.getId());
        select = splitProductMapper.selectByPrimaryKey(select);
        select.setCustomerId(splitProduct.getCustomerId());
        select.setLoginCompanyId(splitProduct.getLoginCompanyId());
        select.setLoginCompanyLogicalCode(splitProduct.getLoginCompanyLogicalCode());
        select.setLoginUserId(splitProduct.getLoginUserId());
        return select;
    }


}
